using System.IO;

namespace Engine.FileFormats3D.C11Undercover.QADFile
{
    public class BlockInfo
    {
        #region Public Fields

        public ushort numberOfLights;

        public ushort numberOfObjects;

        public short offsetLightId;

        public byte value11;
        public byte value12;
        private short firstObject;

        #endregion Public Fields

        #region Internal Fields

        internal uint numberOfPolygons;

        #endregion Internal Fields

        #region Private Fields

        private float blockY;

        private ushort cellX;

        private ushort cellY;

        private uint chunk65K;

        private uint firstPolygon;

        private uint firstSurfaceChunk;

        private int numberOfSurfaceChunks;

        private float x;

        private float y;

        private float z;

        #endregion Private Fields

        #region Public Constructors

        public BlockInfo(
                    ushort cellX,// cellPosition X
                    ushort cellY,// cellPostiion Y
                    uint firstPolygon,//first polgon
                    uint numberOfPolygons,//number of Polygons in Block
                    uint firstTexture,//firstTexture??
                    int numberOfTextures,//number of surfaces??
                    float x,
                    float y,
                    float z,
                    float yHeight,// Y-Height
                    short objectsAvaible,
                    ushort numberOfObjects,
                    short lightsAvaible,
                    ushort numberOfLights,
                    ushort chunkID,
                    byte value11,
                    byte value12
                        )
        {
            this.cellX = cellX;// cellPosition X
            this.cellY = cellY;// cellPostiion Y
            this.firstPolygon = firstPolygon;//first polgon
            this.numberOfPolygons = numberOfPolygons;//number of Polygons in Block
            this.firstSurfaceChunk = firstTexture;//firstTexture??
            this.numberOfSurfaceChunks = numberOfTextures;//number of textures??
            this.x = x;
            this.y = y;
            this.z = z;
            this.blockY = yHeight;// Y-Height
            this.FirstObject = objectsAvaible;
            this.NumberOfObjects = numberOfObjects;
            this.offsetLightId = lightsAvaible;
            this.numberOfLights = numberOfLights;
            this.chunk65K = chunkID;
            this.value11 = value11;
            this.value12 = value12;
        }

        public BlockInfo(int cellX, int cellY)
        {
            this.blockY = 0f;
            this.cellX = (ushort)cellX;
            this.cellY = (ushort)cellY;
            this.chunk65K = 0;
            this.firstPolygon = 0;
            this.firstSurfaceChunk = 0;
            this.numberOfPolygons = 0;
            this.numberOfSurfaceChunks = 0;
            this.value11 = 0;
            this.NumberOfObjects = 0;
            this.numberOfLights = 0;
            this.x = 0;
            this.y = 0;
            this.z = 0;
            this.offsetLightId = -1;
            this.FirstObject = -1;
        }

        #endregion Public Constructors

        #region Public Properties

        public float BlockY
        {
            get { return this.blockY; }
            set { this.blockY = value; }
        }

        public ushort CellX
        {
            get { return this.cellX; }
        }

        public ushort CellY
        {
            get { return this.cellY; }
        }

        public uint Chunk65K
        {
            get { return this.chunk65K; }
            set { this.chunk65K = value; }
        }

        public short FirstObject { get => this.firstObject; set => this.firstObject = value; }

        public uint FirstPolygon
        {
            get { return this.firstPolygon; }
            set { this.firstPolygon = value; }
        }

        public uint FirstSurfaceChunk
        {
            get { return this.firstSurfaceChunk; }
            set { this.firstSurfaceChunk = value; }
        }

        public ushort NumberOfObjects
        {
            get
            {
                return this.numberOfObjects;
            }
            set
            {
                this.numberOfObjects = value;
                if (this.numberOfObjects == 0)
                    this.FirstObject = -1;
            }
        }

        public int NumberOfSurfaceChunks
        {
            get { return this.numberOfSurfaceChunks; }
            set { this.numberOfSurfaceChunks = value; }
        }

        public float X
        {
            get { return this.x; }
            set { this.x = value; }
        }

        public float Y
        {
            get { return this.y; }
            set { this.y = value; }
        }

        public float Z
        {
            get { return this.z; }
            set { this.z = value; }
        }

        #endregion Public Properties

        #region Public Methods

        public static BlockInfo FromStream(BinaryReader br)
        {
            ushort cellPositionX = br.ReadUInt16();// cellPosition X
            ushort cellPositionY = br.ReadUInt16();// cellPostiion Y
            uint firstPolygon = br.ReadUInt32();//first polgon
            uint numberOfPolygonsInBlock = br.ReadUInt32();//number of Polygons in Block
            uint firstSurfaceChunk = br.ReadUInt32();//firstTexture??
            int numberOfSurfaceChunks = br.ReadInt32();//number of textures??
            float x = br.ReadSingle();
            float y = br.ReadSingle();
            float z = br.ReadSingle();
            float height = br.ReadSingle();// Y-Height
            short avaibleObjects = br.ReadInt16();
            if (avaibleObjects > 0)
            { }
            ushort numberOfObjects = br.ReadUInt16();
            //numberOfObjects = br.ReadUInt16();
            short avaibleLights = br.ReadInt16();
            ushort numberOfLights = br.ReadUInt16();
            // numberOfLights = br.ReadUInt16();
            ushort chunk65K = br.ReadUInt16();

            byte value11 = br.ReadByte();
            byte value12 = br.ReadByte();

            return new BlockInfo(cellPositionX,// cellPosition X
                                 cellPositionY,// cellPostiion Y
                                 firstPolygon,//first polgon
                                 numberOfPolygonsInBlock,//number of Polygons in Block
                                 firstSurfaceChunk,//firstTexture??
                                 numberOfSurfaceChunks,//number of textures??
                                 x,
                                 y,
                                 z,
                                 height,// Y-Height
                                 avaibleObjects,
                                 (ushort)numberOfObjects,
                                     avaibleLights,
                                 (ushort)numberOfLights,
                                 chunk65K,

                               value11,
                               value12
                                 );
        }

        public override string ToString()
        {
            //return "cellxy:" + cellX.ToString() + " " + cellY.ToString() + " firstPy:" + firstPolygon.ToString() + "\t" +
            //    numberOfPolygons.ToString() + "\t" + firstSurfaceChunk.ToString() + "\t" + numberOfSurfaceChunks.ToString() + "\t" + X.ToString() + "\t" + Y.ToString() + "\t" + Z.ToString() + "\t" +
            //    blockY.ToString() + "\t" + numberOfObjects.ToString() + "\t" + numberOfLights.ToString() + "\t" + chunk65K.ToString();

            return string.Format("ob: {0}\n\rav: {1}\n\rX: {2}\n\rY: {3}", this.NumberOfObjects, this.FirstObject, this.cellX, this.cellY);
        }

        #endregion Public Methods

        #region Internal Methods

        internal void ResetPolygonData()
        {
            this.chunk65K = 0;
            this.firstPolygon = 0;
            this.firstSurfaceChunk = 0;
            this.numberOfPolygons = 0;
            this.numberOfSurfaceChunks = 0;
        }

        internal void Save(BinaryWriter bw)
        {
            bw.Write(this.cellX);// cellPosition X
            bw.Write(this.cellY);// cellPostiion Y
            bw.Write(this.firstPolygon);//first polgon
            bw.Write(this.numberOfPolygons);//number of Polygons in Block
            bw.Write(this.firstSurfaceChunk);//first Surface Chunk
            bw.Write((uint)this.numberOfSurfaceChunks);//number of SurfaceChunks??
            bw.Write(this.X);
            bw.Write(this.Y);
            bw.Write(this.Z);
            bw.Write(this.blockY);// Y-Height
            //short objectsAvaible = (this.numberOfObjects > 0) ? (short)0 : (short)-1;
            //bw.Write((short)objectsAvaible);
            bw.Write(this.FirstObject);
            bw.Write(this.NumberOfObjects);
            //short lightsAvaible = (this.numberOfLights > 0) ? (short)0 : (short)-1;
            //bw.Write((short)lightsAvaible);
            bw.Write(this.offsetLightId);
            bw.Write(this.numberOfLights);
            bw.Write((ushort)this.chunk65K);
            // TODO: bw.Write((byte)this.value11);
            // TODO: bw.Write((byte)this.value12);
            bw.Write((byte)0);
            bw.Write((byte)0);
        }

        #endregion Internal Methods
    }
}